package org.gwtEss.other;

import com.google.gwt.event.dom.client.HasMouseDownHandlers;
import com.google.gwt.event.dom.client.HasMouseMoveHandlers;
import com.google.gwt.event.dom.client.MouseMoveEvent;
import com.google.gwt.event.dom.client.MouseMoveHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.LayoutPanel;
import com.google.gwt.user.client.ui.Widget;

public class LayoutPanelResizer extends Draggable{
	int startWidth, startHeight, startLeft, startTop;
	private int feather = 5, cornerFeather = 10; 
	enum WIDGET_POSITION {top, left};
	//	boolean dragging = false;
	
	/*boolean draggingEdgeLeft = false, draggingEdgeRight = false,
			draggingEdgeTop = false, draggingEdgeBottom = false, draggingCornerLeftTop = false,
			draggingCornerRightTop = false, draggingCornerLeftBottom = false,
			draggingCornerRightBottom = false;*/
	enum DRAG_REGION {edgeleft, edgeRight, edgeTop, edgeBottom, cornerLeftTop, cornerRightTop, cornerLeftBottom, cornerRightBottom};
	private DRAG_REGION dragRegion; 
//	private HasWidgetResizerRequiredHandlers widget;
	private LayoutPanel widget;
	private boolean isDragging(){
		return dragRegion != null;
//		return isDraggingCorners() || isDraggingHorizontalEdges() || isDraggingVerticalEdges();
	}
	
	public LayoutPanelResizer(LayoutPanel widget) {
		setWidget(widget);
	}
	
	private void addMouseMoveHandler(final HasMouseMoveHandlers widget) {
		System.out.println("Mouse move---");
		widget.addMouseMoveHandler(new MouseMoveHandler() {
			private String currResizeStyle = null;
			@Override
			public void onMouseMove(MouseMoveEvent event) {
				if (isDragging())
					return;
				int x = event.getClientX();
				int y = event.getClientY();
				Widget w = ((Widget)widget);
				if (currResizeStyle != null) w.removeStyleName(currResizeStyle);
				
				DRAG_REGION overArea = findDragRegion(x, y, w.getAbsoluteLeft(), w.getAbsoluteTop(), w.getOffsetWidth(), w.getOffsetHeight());
				
				if (overArea == null)
					currResizeStyle = null; 
				else {
					boolean isWPosAbs = isWidgetPositionedAbsolute((Widget)widget);
					if (isWPosAbs || (overArea != DRAG_REGION.edgeTop && overArea != DRAG_REGION.edgeleft && overArea != DRAG_REGION.cornerLeftTop /*&& overArea != DRAG_REGION.cornerLeftBottom && overArea != DRAG_REGION.cornerRightTop*/))
						w.addStyleName(currResizeStyle = overArea.toString());
				}
				/*
				if (isMouseOverCornerLeftTop(x, y, w.getAbsoluteTop(), w.getAbsoluteLeft()))
					w.addStyleName(currResizeStyle = "seresize");
				else if (isMouseOverCornerRightBottom(x, y, w.getAbsoluteLeft(), w.getAbsoluteTop(), w.getOffsetWidth(), w.getOffsetHeight()))
					w.addStyleName(currResizeStyle = "seresize");
				else if (isMouseOverCornerRightTop(x, y, w.getAbsoluteTop(), w.getAbsoluteLeft(), w.getOffsetWidth()))
					w.addStyleName(currResizeStyle = "neresize");
				else if (isMouseOverCornerLeftBottom(x, y, w.getAbsoluteLeft(), w.getAbsoluteTop(), w.getOffsetHeight()))
					w.addStyleName(currResizeStyle = "neresize");
				else if (isMouseOverEdgeTop(y, w.getAbsoluteTop()))
					w.addStyleName(currResizeStyle = "nresize");
//					DOM.setStyleAttribute(w.getElement(), "cursor", "n-resize");
				else if (isMouseOverEdgeBottom(y, w.getAbsoluteTop(), w.getOffsetHeight()))
					w.addStyleName(currResizeStyle = "sresize");
//					DOM.setStyleAttribute(w.getElement(), "cursor", "s-resize");
				else if (isMouseOverLeftEdge(x, w.getAbsoluteLeft()))
					w.addStyleName(currResizeStyle = "wresize");
//					DOM.setStyleAttribute(w.getElement(), "cursor", "w-resize");
				else if (isMouseOverRightEdge(x, w.getAbsoluteLeft(), w.getOffsetWidth()))
					w.addStyleName(currResizeStyle = "eresize");
				else 
					currResizeStyle = null; */
//				else {
//					w.removeStyleName("nresize");
//					w.removeStyleName("sresize");
//					w.removeStyleName("wresize");
//					w.removeStyleName("eresize");
//				}
//					DOM.setStyleAttribute(w.getElement(), "cursor", "e-resize");
				
			}
		});
	}
	@Override
	public void onDragStart(int mouseX, int clientY) {
		startWidth = onWidgetWidth();
		startHeight = getWidgetHeight();
		startLeft = getWidgetLeft();
		startTop = getWidgetTop();
		
		dragRegion = findDragRegion(mouseX, clientY, startLeft, startTop, startWidth, startHeight);
		/*
		draggingEdgeBottom = isMouseOverEdgeBottom(clientY, startTop, startHeight);
		draggingEdgeLeft = isMouseOverLeftEdge(mouseX, startLeft);
		draggingEdgeRight = isMouseOverRightEdge(mouseX, startLeft, startWidth);
		draggingEdgeTop = isMouseOverEdgeTop(clientY, startTop);
		draggingCornerLeftBottom = isMouseOverCornerLeftBottom(mouseX, clientY, startLeft, startTop, startHeight);
		draggingCornerLeftTop = isMouseOverCornerLeftTop(mouseX, clientY, startTop, startLeft);
		draggingCornerRightBottom = isMouseOverCornerRightBottom(mouseX, clientY, startLeft, startTop, startWidth, startHeight);
		draggingCornerRightTop = isMouseOverCornerRightTop(mouseX, clientY, startTop, startLeft, startWidth);*/
		
		System.out.println(isDragging());
		if (!isDragging())
			return;
//		onWidthChange(startWidth);
//		onHeightChange(startHeight);
		onResizeStart();
//		((Widget)widget).addStyleName("seperator-drag");
		
	}
	@Override
	protected boolean isPreventDefault(int x, int y) {
		return isDragging();
	}
	
	private DRAG_REGION findDragRegion(int x, int y, int left, int top, int width, int height){
		if (((x <= left + feather) && (y <= top + cornerFeather)) || ((y <= top + feather) && (x <= left + cornerFeather))) return DRAG_REGION.cornerLeftTop;
		if (((x >= left + width - feather) && (y <= top + cornerFeather)) || ((y <= top + feather) && (x >= left + width - cornerFeather))) return DRAG_REGION.cornerRightTop;
		if (((x <= left + feather) && (y >= top + height - cornerFeather)) || ((y >= top + height - feather) && (x <= left + cornerFeather))) return DRAG_REGION.cornerLeftBottom;
		if (((x >= left + width - feather) && (y >= top + height - cornerFeather)) || ((y >= top + height - feather) && (x >= left + width - cornerFeather))) return DRAG_REGION.cornerRightBottom;
		
		if (x >= left + width-feather /*&& x <= left + width */) return DRAG_REGION.edgeRight;
		if (/*x >= left && */x <= left + feather) return DRAG_REGION.edgeleft;
		if (y >= top + height - feather /*&& y <= top + height*/) return DRAG_REGION.edgeBottom;
		if (/*y >= top && */y <= top + feather) return DRAG_REGION.edgeTop;
		return null; 
	}
	/*
	private boolean isMouseOverRightEdge(int x, int left, int width){
		return (x >= left + width-feather && x <= left + width ); 
	}
	private boolean isMouseOverLeftEdge(int x, int left){
		return (x >= left && x <= left + feather); 
	}
	private boolean isMouseOverEdgeBottom(int y, int top, int height){
		return (y >= top + height - feather && y <= top + height); 		
	}
	private boolean isMouseOverEdgeTop(int y, int top){
		return (y >= top && y <= top + feather);
	}
	private boolean isMouseOverCornerLeftTop(int x, int y, int top, int left){
		return ((x <= left + feather) && (y <= top + cornerFeather)) || ((y <= top + feather) && (x <= left + cornerFeather));
	}
	private boolean isMouseOverCornerRightTop(int x, int y, int top, int left, int width){
		return ((x >= left + width - feather) && (y <= top + cornerFeather)) || ((y <= top + feather) && (x >= left + width - cornerFeather));
	}
	private boolean isMouseOverCornerLeftBottom(int x, int y, int left, int top, int height){
		return ((x <= left + feather) && (y >= top + height - cornerFeather)) || ((y >= top + height - feather) && (x <= left + cornerFeather));
	}
	private boolean isMouseOverCornerRightBottom(int x, int y, int left, int top, int width, int height){
		return ((x >= left + width - feather) && (y >= top + height - cornerFeather)) || ((y >= top + height - feather) && (x >= left + width - cornerFeather));
	}*/

	@Override
	public void onDragEnd(int mouseX, int mouseY, int deltaX, int deltaY) {
		if (!isDragging()) return;
//		((Widget)widget).removeStyleName("seperator-drag");
		onDrag(mouseX, mouseY, deltaX, deltaY);
		onResizeEnd();
		dragRegion = null;
//		draggingEdgeLeft = draggingEdgeRight = draggingEdgeTop = draggingEdgeBottom = draggingCornerLeftTop = draggingCornerRightTop = draggingCornerLeftBottom = draggingCornerRightBottom = false;
	}
	
	@Override
	public void onDrag(int mouseX, int mouseY, int deltaX, int deltaY) {
		System.out.println("deltaX: " + deltaX + ", deltaY: " + deltaY);
		if (!isDragging()) return;
		if (deltaX==0 && deltaY == 0) return;
		int width = startWidth - deltaX;
		int height = startHeight - deltaY;
//		if (width > 0 && ( isDraggingVerticalEdges() || isDraggingCorners()))
		
		switch (dragRegion){
			case cornerLeftBottom:
				doLeftEdgeResize(width, deltaX);
				doBottomEdgeResize(height);
				break;
			case cornerRightBottom: 
				doRightEdgeResize(width);
				doBottomEdgeResize(height);
				break;
			case cornerLeftTop: 
				doLeftEdgeResize(width, deltaX);
				doTopEdgeResize(height, deltaY);
				break;
			case cornerRightTop:
				doRightEdgeResize(width);
				doTopEdgeResize(height, deltaY);
				break;
			case edgeBottom:
				doBottomEdgeResize(height);
				break;
			case edgeleft:
				doLeftEdgeResize(width, deltaX);
				break;
			case edgeRight:
				doRightEdgeResize(width);
				break;
			case edgeTop:
				doTopEdgeResize(height, deltaY);
				break;
		}
		/*
		if (width > 0 && draggingEdgeLeft){
			if (onLeftChange(startLeft - deltaX))
				onWidthChange(width + deltaX*2);
		}
		if (height > 0 && draggingEdgeTop){
			if (onTopChange(startTop - deltaY))
				onHeightChange(height + deltaY*2);			
		}
		
		if (width > 0 && draggingEdgeRight)
			onWidthChange(width);
//		if (height > 0 && (isDraggingHorizontalEdges() || isDraggingCorners()))
		
		if (height > 0  && draggingEdgeBottom)
			onHeightChange(height);*/
	}
	
	private void doLeftEdgeResize(int width, int deltaX){
		if (width > 0){
			if (onWidgetPositionChange(WIDGET_POSITION.left, startLeft - deltaX))
				onWidthChange(width + deltaX*2);
		}
	}
	private void doRightEdgeResize(int width){
		if (width > 0)
			onWidthChange(width);
	}
	private void doTopEdgeResize(int height, int deltaY){
		if (height > 0){
			if (onWidgetPositionChange(WIDGET_POSITION.top, startTop - deltaY))
				onHeightChange(height + deltaY*2);			
		}
	}
	private void doBottomEdgeResize(int height){
		if (height > 0 )
			onHeightChange(height);	
	}
	/*private boolean isDraggingCorners(){
		return draggingCornerLeftBottom || draggingCornerRightBottom || draggingCornerRightTop || draggingCornerLeftTop;
	}
	private boolean isDraggingHorizontalEdges() {
		return draggingEdgeTop || draggingEdgeBottom; 
	}
	private boolean isDraggingVerticalEdges(){
		return draggingEdgeLeft || draggingEdgeRight; 
	}*/
	public int getFeather() {
		return feather;
	}
	public void setFeather(int feather) {
		this.feather = feather;
	}
	protected void onResizeStart(){}
	protected void onResizeEnd(){}
//	protected boolean onLeftChange(int left) {
//		Element elem = ((Widget)widget).getElement(); 
//		String position = DOM.getStyleAttribute(elem, "position");
//		if (position.trim().equalsIgnoreCase("absolute")){
//		    elem.getStyle().setPropertyPx("left", left);
//		    return true; 
//		}
//		return false; 
//	}
	protected boolean isWidgetPositionedAbsolute(Widget w){
		Element elem = w.getElement(); 
		String position = DOM.getStyleAttribute(elem, "position");
		return position.trim().equalsIgnoreCase("absolute"); 
	}
	protected boolean onWidgetPositionChange(WIDGET_POSITION widgetPosition, int pxs) {
		Widget w = (Widget)widget; 
		if (isWidgetPositionedAbsolute(w)){
			DOM.setStyleAttribute(w.getElement(), widgetPosition.toString(), pxs + "px");
//		    w.getElement().getStyle().setPropertyPx(widgetPosition.toString(), pxs);
		    return true; 
		}
		return false; 
	}
	protected void onWidthChange(int width) {
		System.out.println(((Widget)widget).getElement().getStyle().getBorderStyle() + "<- border width");
		((Widget)widget).setWidth(width + "px");
	}
	protected int onWidgetWidth() {
		return ((Widget)widget).getOffsetWidth();
	}
	protected int getWidgetTop() {
		return ((Widget)widget).getAbsoluteTop();
	}
	protected int getWidgetLeft() {
		return ((Widget)widget).getAbsoluteLeft();
	}
	protected int getWidgetHeight() {
		return ((Widget)widget).getOffsetHeight();
	}
	protected void onHeightChange(int height) {
		((Widget)widget).setHeight(height + "px");
	}
	
//	@Override
//	public void setWidget(HasMouseDownHandlers widget) {
////		assert false: "use public void setWidget(HasWidgetResizerRequiredHandlers resizerWidget) instead";
//		setWidget((Widget)widget);
//	}
	public void setWidget(LayoutPanel widget) {
		assert widget instanceof Widget && widget instanceof HasMouseDownHandlers && widget instanceof HasMouseMoveHandlers: "ResizableWidget should be instance of HasWidgetResizerRequiredHandlers and Widget";
		this.widget = widget;
		addMouseMoveHandler((HasMouseMoveHandlers)widget);
		super.setWidget((HasMouseDownHandlers)widget);
	}
//	public void setWidget(HasWidgetResizerRequiredHandlers widget) {
//		setWidget((Widget)widget);
////		this.widget = resizerWidget;	
//	}
}
